package com.jec.module.business.record;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.tritonus.share.sampled.TConversionTool;

import com.jec.base.core.PipeTask;
import com.jec.module.business.entity.RecordSegment;
import com.jec.protocol.unit.BytesWrap;
import com.jec.utils.Constants;

import lombok.extern.log4j.Log4j;


/**
 * Created by jeremyliu on 6/19/16.
 */
@Log4j
public class EncodeTask extends PipeTask<BytesWrap>{

    private FileOutputStream fos;

    private String pcmFile;

    private long recordByte = 0;

    private long lastSegByte = 0;

    private boolean isSegment = false;

    private byte[] buffer = new byte[2048];

    private List<RecordSegment> recordSegmentList = new ArrayList<>();

    private final static long segmentSize = Constants.RecordSegmentSize;
    
    public static ExecutorService executor = Executors.newFixedThreadPool(3);


    public EncodeTask(String file, boolean isSegment){
        int	ind = file.lastIndexOf(".");
        if (ind == -1
                || ind == file.length()
                || file.lastIndexOf(File.separator) > ind) {
            // when dot is at last position,
            // or a slash is after the dot, there isn't an extension
            pcmFile =  file;
        }else
            pcmFile = file.substring(0, ind);
        this.isSegment = isSegment;
    }

    public long getRecordTime(){
        return recordByte/16;
    }

    public List<RecordSegment> getRecordSegmentList(){
        return recordSegmentList;
    }

    @Override
    public boolean prepare(){
        try {
            createSegement();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    private RecordSegment createSegement() throws IOException{
        int size = recordSegmentList.size();
        RecordSegment segment = new RecordSegment(pcmFile,size);
        recordSegmentList.add(segment);
        String originFile = segment.getOriginFile();
        File file = new File(originFile);
        file.getAbsolutePath();
        fos = new FileOutputStream(originFile);
        return segment;
    }

    @Override
    public boolean done(){

        try {
            if(fos != null) {
                fos.flush();
                fos.close();
                RecordSegment recordSegment = recordSegmentList.get(recordSegmentList.size()-1);
                recordSegment.setPeriod(lastSegByte/16);
                String pcmFile = recordSegment.getOriginFile();
                
                
                executor.execute(new EncodeThread(pcmFile,recordSegment.getTargetFile()));
                
                /*
                RecordEncode.encodeByJump3rV2(pcmFile,recordSegment.getTargetFile());
                // remove pcm file
                File pcm = new File(pcmFile);
                pcm.delete();
                
                log.warn("encode task done. pcm=" + pcmFile);
                */
                
                return true;
            }
        } catch (IOException e) {
            log.warn("done exception", e);
        }
        return false;
    }

    @Override
    public boolean work(BytesWrap data) {
        try {
            int offset = data.offset();
            int length = data.length();

            TConversionTool.alaw2pcm16(data.buffer(), offset, buffer, 0, length, true);
            length *=2;
            //如果设置分段
            if(isSegment)
                segment(length);

            fos.write(buffer, 0, length);
            recordByte += length;
            lastSegByte += length;
            return true;
        }catch (IOException e){
        	log.warn("encode data error", e);
            return false;
        }
    }

    private void segment(int length) throws IOException{
        if(lastSegByte + length > segmentSize){
        	log.info("segment size=" + this.getRecordTime());
            done();
            createSegement();
            lastSegByte = 0;
        }
    }
    
    @Log4j
    public static class EncodeThread implements Runnable {
    	
    	private String source;
    	private String target;
    	
		public EncodeThread(String source, String target) {
			super();
			this.source = source;
			this.target = target;
		}


		@Override
		public void run() {
			
			log.info("Encode start:");
			log.info("  source: " + source);
			log.info("  target: " + target);
			
			long start = System.currentTimeMillis();
			
			// 
            RecordEncode.encodeByJump3rV2(source, target);
            
            // remove pcm file
            log.info("  Deleting source file...");
            File pcm = new File(source);
            pcm.delete();
            
            log.info("Encode finished with: " + (System.currentTimeMillis() - start));
			
		}
    	
    	
    	
    }
}
